import importlib
import traceback
from . import errcode
from .packet import Packet
from .errcode import ImError, get_error_message

__all__ = ['BaseHandler', 'load_handler', 'handle']


class BaseHandler:
    def handle(self, connection, packet):
        raise NotImplementedError

    def __call__(self, connection, packet):
        return self.handle(connection, packet)


_handlers = {}


def load_handler(command):
    if command not in _handlers:
        module = importlib.import_module("." + command, "pyim.commands")
        handler = getattr(module, "Handler")
        if not handler:
            raise ModuleNotFoundError()

        if not issubclass(handler, BaseHandler):
            raise TypeError(handler.__name__)

        _handlers[command] = handler()
    return _handlers[command]


def handle(connection, packet):
    assert isinstance(packet, Packet)
    try:
        load_handler(packet["command"])(connection, packet)
    except ImError as e:
        traceback.print_exc()
        err_reply = Packet(id=packet["id"],
                           command=packet['command'],
                           errcode=e.errcode,
                           errmsg=get_error_message(e.errcode))
        connection.route(err_reply)
    except Exception as e:
        traceback.print_exc()
        err_reply = Packet(id=packet["id"],
                           command=packet['command'],
                           errcode=errcode.SERVER_ERROR,
                           errmsg=str(e))
        connection.route(err_reply)
